#pragma once

//让服务器变为守护进程
#include<iostream>
#include<unistd.h>
#include<sys/types.h>
#include<signal.h>
#include<fcntl.h>

//想要将一个进程变为守护进程首先是让其成为独立会话 -> 调用 setsid ，要求：调用setsid 的进程不能是其所在进程组的组长
//只能有1个前台进程，而可以有多个后台进程

void Deamon()
{
    //守护进程需要忽略一些信号，例如：SIGCHLD、SIGPIPE
    //忽略SIGCHLD是因为，此处tcp 通信底层使用多进程的方式实现多执行流；而对于SIGPIPE是因为，
    //在管道中，读端不读，且将读端关闭，而此时写端还在写的话，OS会发送SIGPIPE杀死写端；同理，
    //对于此处的tcp通信来说，当客户端退出，服务端的OS会发送SIGPIPE 信号
    signal(SIGCHLD,SIG_IGN);
    signal(SIGPIPE, SIG_IGN);

    //创建子进程，父进程退出，子进程继续执行后面的代码
    if(fork()>0) 
    {
        exit(0);
    }

    //将守护进程的工作路径更改未根目录，这是因为未来项目会将文件分放在各种文件中；而在下载的时候
    //有些客户端会将对应目录下的文件拷贝到系统中对象的路径下；而每一个客户端下载该软件的路径是不一样的，
    //就有可能导致server 在运行的时候可能找不到其所对应的配置文件；
    //所以将工作路径改为根目录，可以解决这个问题；况且，这种处理方式可以使用绝对路径的方式找到配置文件
    chdir("/");

    //子进程为独立的会话
    setsid();

    //处理守护进程的stdin stdout stderr, 可以直接关闭，也可以使用dup2 重定向到 /dev/null 中
    int fd = open("/dev/null" , O_RDWR);
    if(fd >= 0)
    {
        dup2(fd, 0);
        dup2(fd, 1);
        dup2(fd, 2);
    }
}